﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Autodesk.Revit.DB;
using YArchitech.Revit;
using YJKArchUtils.Utils;
using YJKRevitKernel.XYZUtility;
using YJKCopyModel.QuickModelFrame;
using YJKPresentation.Utils;

namespace YJKCopyModel.YJKRevitWndr
{
	[Rebuilder(RebuilderName = "DoorAndWindowRebuilder")]
	public class DoorAndWindowRebuilder : IRevitModelRebuilder
	{
		public bool TryRebuildRevitModel(Autodesk.Revit.DB.Document inputDoc, RevitModelRequest inputReqeust, out BuildData buildData)
		{
			buildData = new BuildData();
			buildData.NeedResponse = true;
			try
			{
				DoorAndWindowRevitModelRequest doorAndWindowRevitModelRequest = inputReqeust as DoorAndWindowRevitModelRequest;
				bool flag = doorAndWindowRevitModelRequest == null;
				if (flag)
				{
					return false;
				}
				DoorAndWindowCadElement doorAndWindowCadElement = doorAndWindowRevitModelRequest.RequestData as DoorAndWindowCadElement;
				bool flag2 = doorAndWindowCadElement == null;
				if (flag2)
				{
					return false;
				}
				XYZ useLocationPoint = doorAndWindowCadElement.ThisBlockRefInfo.UseLocationPoint;
				useLocationPoint.SetZ(0.0);
				XYZ handDir = doorAndWindowCadElement.ThisBlockRefInfo.HandDir;
				double width = doorAndWindowRevitModelRequest.ThisConfigInfo.Width;
				FamilySymbol specifiedFamilySymbol = doorAndWindowRevitModelRequest.ThisConfigInfo.SpecifiedFamilySymbol;
				bool flag3 = specifiedFamilySymbol == null || !specifiedFamilySymbol.IsValidObject;
				if (flag3)
				{
					return false;
				}
				Wall wall = this.GetHostWall(inputDoc, useLocationPoint, handDir);
				bool flag4 = wall == null;
				if (flag4)
				{
					wall = this.CreateHostWall(inputDoc, useLocationPoint, handDir, YJKPresentation.Utils.Common.MMToFeet(width * 1.2));
					bool flag5 = wall == null;
					if (flag5)
					{
						throw new Exception("创建门窗宿主墙失败。");
					}
				}
				double num = width;
				Parameter parameter = specifiedFamilySymbol.GetParameter(BuiltInParameter.CASEWORK_WIDTH);
				bool flag6 = parameter != null;
				if (flag6)
				{
					num = double.Parse(parameter.AsValueString());
				}
				double num2 = num + DoorAndWindowDefultSet.DoorWindowSideWallReserveLen;
				LocationCurve locationCurve = wall.Location as LocationCurve;
				double num3 = YJKPresentation.Utils.Common.FeetToMM(locationCurve.Curve.Length);
				bool flag7 = YJKPresentation.Utils.Geometry.LessThan(num3, num2);
				if (flag7)
				{
					this.ExtendWall(wall, (num2 - num3) / 2.0);
				}
				Level level = inputDoc.GetElement(wall.LevelId) as Level;
				FamilyInstance doorAndWindow = inputDoc.Create.NewFamilyInstance(useLocationPoint, specifiedFamilySymbol, wall, level, (Autodesk.Revit.DB.Structure.StructuralType)0);
				Parameter parameter2 = doorAndWindow.GetParameter(BuiltInParameter.INSTANCE_SILL_HEIGHT_PARAM);
				double bottomHeight = doorAndWindowRevitModelRequest.ThisConfigInfo.BottomHeight;
				parameter2.Set(YJKPresentation.Utils.Common.MMToFeet(bottomHeight));
				buildData.UseWork = delegate
				{
					try
					{
						XYZ faceDir = doorAndWindowCadElement.ThisBlockRefInfo.FaceDir;
						bool flag8 = !XYZUtilityMethod.IsSameDirection(doorAndWindow.FacingOrientation, faceDir);
						if (flag8)
						{
							doorAndWindow.flipFacing();
						}
						XYZ handDir2 = doorAndWindowCadElement.ThisBlockRefInfo.HandDir;
						bool flag9 = !XYZUtilityMethod.IsSameDirection(doorAndWindow.HandOrientation, handDir2);
						if (flag9)
						{
							doorAndWindow.flipHand();
						}
					}
					catch (Exception ex)
					{
					}
				};
				buildData.CreatedElement = doorAndWindow;
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		private Wall GetHostWall(Autodesk.Revit.DB.Document doc, XYZ ptPos, XYZ vcDir)
		{
			try
			{
				FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc, doc.ActiveView.Id);
				List<Element> list = filteredElementCollector.OfCategory(BuiltInCategory.OST_Walls).ToList<Element>();
				foreach (Element element in list)
				{
					LocationCurve locationCurve = element.Location as LocationCurve;
					IntersectionResult intersectionResult = locationCurve.Curve.Project(ptPos);
					XYZ xyz = new XYZ(intersectionResult.XYZPoint.X, intersectionResult.XYZPoint.Y, 0.0);
					bool flag = intersectionResult.XYZPoint.IsAlmostEqualTo(ptPos);
					if (flag)
					{
						XYZ basisX = locationCurve.Curve.ComputeDerivatives(intersectionResult.Parameter, false).BasisX;
						bool flag2 = YJKPresentation.Utils.Geometry.IsParallel(basisX, vcDir);
						if (flag2)
						{
							return element as Wall;
						}
					}
				}
			}
			catch (Exception ex)
			{
				Trace.Assert(true, ex.Message);
			}
			return null;
		}

		private Wall CreateHostWall(Autodesk.Revit.DB.Document doc, XYZ ptPos, XYZ vcDir, double dLen)
		{
			Wall result;
			try
			{
				XYZ xyz = ptPos - vcDir.Normalize() * dLen / 2.0;
				XYZ xyz2 = ptPos + vcDir.Normalize() * dLen / 2.0;
				Curve curve = Line.CreateBound(xyz, xyz2);
				ElementId id = doc.ActiveView.GenLevel.Id;
				Wall wall = Wall.Create(doc, curve, id, false);
				WallType wallType = this.CreateNewWallType(doc, "HY-建-砖-200");
				bool flag = wall != null && wallType != null;
				if (flag)
				{
					wall.WallType = wallType;
				}
				doc.Regenerate();
				result = wall;
			}
			catch (Exception)
			{
				result = null;
			}
			return result;
		}

		private WallType CreateNewWallType(Autodesk.Revit.DB.Document doc, string strWallTypeName)
		{
			WallType wallType = null;
			List<WallType> allWallTypes = this.GetAllWallTypes(doc);
			WallType wallType2 = allWallTypes.Find((WallType item) => item.Name == strWallTypeName);
			bool flag = wallType2 != null;
			WallType result;
			if (flag)
			{
				result = wallType2;
			}
			else
			{
				IDictionary<int, CompoundStructureError> dictionary = null;
				IDictionary<int, int> dictionary2 = null;
				try
				{
					bool flag2 = wallType == null;
					if (flag2)
					{
						foreach (WallType wallType3 in allWallTypes)
						{
							bool flag3 = wallType3.Kind == null && wallType3.GetCompoundStructure() != null;
							if (flag3)
							{
                                bool flag4 = wallType3.GetCompoundStructure().IsValid(doc, out dictionary, out dictionary2);
								if (flag4)
								{
									wallType = (wallType3.Duplicate(strWallTypeName) as WallType);
									break;
								}
							}
						}
					}
					List<CompoundStructureLayer> list = new List<CompoundStructureLayer>();
                    CompoundStructureLayer item2 = new CompoundStructureLayer(YJKPresentation.Utils.Common.MMToFeet(200.0), (MaterialFunctionAssignment)1, this.GetMaterialId(doc, "砖", "砌体-砖"));
					list.Add(item2);
					CompoundStructure compoundStructure = wallType.GetCompoundStructure();
					compoundStructure.SetLayers(list);
					wallType.SetCompoundStructure(compoundStructure);
				}
				catch (Exception ex)
				{
					return null;
				}
				result = wallType;
			}
			return result;
		}

		private List<WallType> GetAllWallTypes(Autodesk.Revit.DB.Document doc)
		{
			List<WallType> list = new List<WallType>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			IList<Element> list2 = filteredElementCollector.OfClass(typeof(WallType)).ToElements();
			foreach (Element element in list2)
			{
				WallType wallType = element as WallType;
				bool flag = wallType == null;
				if (!flag)
				{
					list.Add(wallType);
				}
			}
			return list;
		}

		private ElementId GetMaterialId(Autodesk.Revit.DB.Document doc, string strMaterialName, string strFillPatternName)
		{
			List<Material> allMaterial = YJKArchUtils.Utils.Common.GetAllMaterial(doc);
			ElementId elementId = null;
			foreach (Material material in allMaterial)
			{
				bool flag = strMaterialName == material.Name;
				if (flag)
				{
					elementId = material.Id;
					break;
				}
			}
			bool flag2 = null == elementId;
			if (flag2)
			{
				Material material2 = allMaterial[0].Duplicate(strMaterialName);
				YJKArchUtils.Utils.Common.SetMaterialByFillPattern(doc, strFillPatternName, ref material2, true);
				elementId = material2.Id;
			}
			return elementId;
		}

		private void ExtendWall(Wall wall, double dExtendLen)
		{
			Location location = wall.Location;
			LocationCurve locationCurve = location as LocationCurve;
			Curve curve = locationCurve.Curve;
			bool flag = !(curve is Line);
			if (!flag)
			{
				Line line = curve as Line;
				XYZ endPoint = line.GetEndPoint(0);
				XYZ endPoint2 = line.GetEndPoint(1);
				XYZ xyz = endPoint - line.Direction * YJKPresentation.Utils.Common.MMToFeet(dExtendLen);
				XYZ xyz2 = endPoint2 + line.Direction * YJKPresentation.Utils.Common.MMToFeet(dExtendLen);
				Line curve2 = Line.CreateBound(xyz, xyz2);
				locationCurve.Curve = curve2;
			}
		}
	}
}
